﻿using System;
using System.Diagnostics;
using System.ServiceModel;
using System.Threading;
using WcfSyncAsync.Service;

namespace WcfSyncAsync.Client
{
    class Program
    {
        static int _callbacksleep = 0;

        static void Main(string[] args)
        {
            Console.WriteLine("Waiting for host to initialize...");
            Thread.Sleep(2000); // Give Host the time to start and open in case of multiple startup projects

            string mode = args[0];
            int callcount = Convert.ToInt32(args[1]);
            int clientsleep = Convert.ToInt32(args[2]);
            int servicesleep = Convert.ToInt32(args[3]);
            _callbacksleep = Convert.ToInt32(args[4]);

            if (mode == "ThreadPoolAsync")
            {
                SimpleService simpleService = new SimpleService();
                for (int c = 0; c < callcount; c++)
                {
                    SimpleService.ProcessMessageDelegate pmd = new SimpleService.ProcessMessageDelegate(simpleService.ProcessMessage);
                    try
                    {
                        Console.WriteLine(string.Format("Thread {0} calling BeginInvoke with message {1}.", Thread.CurrentThread.ManagedThreadId, c));
                        pmd.BeginInvoke(mode, servicesleep, new AsyncCallback(ThreadPoolCallback), pmd);
                        Thread.Sleep(clientsleep);
                    }
                    catch (Exception exc)
                    {
                        Console.WriteLine(string.Format("Exception on thread {0}: {1}", Thread.CurrentThread.ManagedThreadId, exc.ToString()));
                    }
                }
            }
            else if (mode == "WcfSync")
            {
                ChannelFactory<ISimpleService> cf = new ChannelFactory<ISimpleService>(mode);

                for (int c = 0; c < callcount; c++)
                {
                    Thread t1 = new Thread(() =>
                    {
                        ISimpleService simpleService = cf.CreateChannel();
                        Console.WriteLine(string.Format("Thread {0} sending a message {1}, waiting for reply...", Thread.CurrentThread.ManagedThreadId, c));
                        try
                        {
                            simpleService.ProcessMessage(mode, servicesleep);
                            Thread.Sleep(clientsleep);
                        }
                        catch (Exception exc)
                        {
                            Console.WriteLine(string.Format("Exception on thread {0}: {1}", Thread.CurrentThread.ManagedThreadId, exc.ToString()));
                        }
                    });
                    t1.Start();
                }
            }
            else if (mode == "WcfAsync")
            {
                ChannelFactory<ISimpleServiceAsync> cf = new ChannelFactory<ISimpleServiceAsync>(mode);

                for (int c = 0; c < callcount; c++)
                {
                    ISimpleServiceAsync simpleServiceAsync = cf.CreateChannel();
                    Console.WriteLine(string.Format("Thread {0} calling BeginProcessMessage with message {1}.", Thread.CurrentThread.ManagedThreadId, c));
                    try
                    {
                        IAsyncResult asyncResult = simpleServiceAsync.BeginProcessMessage(mode, servicesleep, new AsyncCallback(WcfCallback), simpleServiceAsync);
                        Thread.Sleep(clientsleep);
                    }
                    catch (Exception exc)
                    {
                        Console.WriteLine(string.Format("Exception on thread {0}", Thread.CurrentThread.ManagedThreadId, exc.ToString()));
                    }
                }
            }

            Console.WriteLine("Finished, hit enter.");
            Console.ReadLine();
        }

        private static void WcfCallback(IAsyncResult asyncResult)
        {
            Console.WriteLine("SimpleService.ProcessMessage - Going to sleep for " + _callbacksleep);
            Trace.WriteLine("SimpleService.ProcessMessage - Going to sleep for " + _callbacksleep);
            Thread.Sleep(_callbacksleep);

            ISimpleServiceAsync simpleServiceAsync = asyncResult.AsyncState as ISimpleServiceAsync;
            bool error = false;
            try
            {
                simpleServiceAsync.EndProcessMessage(asyncResult);
            }
            catch (Exception exc)
            {
                error = true;
                Console.WriteLine("Program.Callback: " + exc.ToString());
                Trace.WriteLine("Program.Callback: " + exc.ToString());
            }

            if (!error)
            {
                Console.WriteLine("Program.Callback finished.");
                Trace.WriteLine("Program.Callback finished.");
            }
        }

        private static void ThreadPoolCallback(IAsyncResult asyncResult)
        {
        }
    }
}